#include "basic_utils.hh"


void deleteIplImage(IplImage *img)
{

    cvReleaseImage(&img);
// #ifdef DEBUG
//     std::cout << "Liberado IplImage" << std::endl;
// #endif /* DEBUG  */
}


void deleteCvMat(CvMat *mat)
{

    cvReleaseMat(&mat);
// #ifdef DEBUG
//     std::cout << "Liberado IplImage" << std::endl;
// #endif /* DEBUG  */
}

void deleteFileStorage(CvFileStorage *fs)
{
    cvReleaseFileStorage(&fs);
}

void deleteVideoWriter(CvVideoWriter *vw)
{
    cvReleaseVideoWriter(&vw);
}


void deleteCvKalman(CvKalman * kalman)
{
    cvReleaseKalman(&kalman);

}

void print_arr(const CvArr *arr, bool transpose, const char *format)
{
    print_arr_mul(arr, 1, transpose, format);
}

void print_arr_mul(const CvArr *arr, float mul, bool transpose, const char *format)
{

    CvMat *mat, head;
    char format2[100] = "%6.2f ";
    mat = cvGetMat(arr, &head);
    CvMat *mat2 = cvCreateMat(mat->cols, mat->rows, mat->type);
    if(transpose)
    {
	cvTranspose(mat, mat2);
	mat = mat2;
    }
    
    if (format != NULL)
	strcpy(format2, format);
	
    
    for(int ai=0; ai<mat->rows; ai++){
	for(int bi=0; bi<mat->cols; bi++){
	    printf(format2, cvGetReal2D(mat, ai, bi)*mul);
	    //std::cout << cvGetReal2D(mat, ai, bi) << " ";
	}
	std::cout << std::endl;
    }

    if(transpose)
	cvTranspose(mat, mat);

    cvReleaseMat(&mat2);

}

bool is_box_in_image(const CvRect r, const IplImage *img)
{

    CvRect a = cvRect(0,0, img->width, img->height);
    CvRect t;
    
    t = cvMaxRect(&r, &a);
    
    if(t.x <0 || t.y<0 || t.width != a.width || t.height != a.height)
	return false;

    return true;
}


CvMat * AgruparMatriz2new(CvMat * mat, CvMat *mask)
{
    CvMat *small = cvCreateMat(cvCountNonZero(mask), mat->cols, mat->type);
    AgruparMatriz(mat, small, mask);
    return small;
}

void AgruparMatriz(CvMat ** mat, CvMat *mask)
{
    CvMat *small = cvCreateMat(cvCountNonZero(mask), (*mat)->cols, (*mat)->type);
    AgruparMatriz(*mat, small, mask);
    cvReleaseMat(mat);
    *mat = small;
    return;
}

void AgruparMatriz(CvMat * mat, CvMat * mask)
{
    CvMat * small = AgruparMatriz2new(mat, mask);
    //small tiene los nuevos datos
    //se borran los datos de mat
    cvReleaseData(mat);
    //el puntero de datos de mat apunta al de data (small)
    cvInitMatHeader(mat, small->rows, small->cols, small->type, small->data.fl);
    //ahora borra la extructura de datos de small, pero no los datos
    cvFree((void**)&small);
}

void AgruparMatriz(CvMat * mat, CvMat *small, CvMat *mask)
{
    int i, j, k=0, n2;
    n2 = mat->rows;
    for (i=0; i<n2; i++)
    {
	if (cvGetReal1D(mask, i))
	{
	    for (j=0; j<mat->cols; j++)
		cvSetReal2D(small, k,j, cvGetReal2D(mat,i,j));
	    k++;
	}
    }
}
    
int DeleteRow(CvMat **mat, int n)
{
    int rows = (*mat)->rows-1;
    int cols = (*mat)->cols;
    CvMat *mat2 = cvCreateMat(rows, cols, (*mat)->type);
    int i, j;
    for (i=0; i<n; i++)
    {
	for (j=0; j<cols; j++)
	    cvSetReal2D(mat2, i,j, cvGetReal2D(*mat,i,j));
    }
    for (i=n; i<rows; i++)
    {
	for (j=0; j<cols; j++)
	    cvSetReal2D(mat2, i,j, cvGetReal2D(*mat,i+1,j));
    }

    cvReleaseMat(mat);
    *mat = mat2;
    return rows;
}


void AddRow(CvMat * mat)
{
    CvMat * big = AddRow2new(mat);
    //small tiene los nuevos datos
    //se borran los datos de mat
    cvReleaseData(mat);
    //el puntero de datos de mat apunta al de data (small)
    cvInitMatHeader(mat, big->rows, big->cols, big->type, big->data.fl);

    CvMat big2, mat2;
    cvGetRow(big, &mat2, mat->rows-1);
    cvGetRow(big, &big2, mat->rows);
    cvCopy(&mat2, &big2);
    //ahora borra la extructura de datos de small, pero no los datos
    cvFree((void**)&big);
}

CvMat * AddRow2new(CvMat * mat)
{
    CvMat *big = cvCreateMat(mat->rows+1, mat->cols, mat->type);
    CvMat big2;
    cvGetRows(big, &big2, 0, mat->rows);
    cvCopy(mat, &big2);
    
    return big;
}

void AddRow2new(CvMat **mat)
{
    *mat = AddRow2new(*mat);
}
